from winpcapy import WinPcapDevices
from winpcapy import WinPcapUtils

# dpkt这个库将数据帧解析成 极其方便使用的对象，使用它可以让我们为你更关注数据包本身内容，而不是怎么去费力把字节数据 捣鼓成能直接识别的信息。
import dpkt
import time
import datetime


# WinPcapDevices这个类实现了本机网卡设备的匹配与查找，WinPcapDevices.list_devices()可以直接打印出本机所有的网络设备。
# list_device = WinPcapDevices.list_devices()
# print(list_device)


def packet_callback(win_pcap, param, header, pkt_data):
    eth = dpkt.ethernet.Ethernet(pkt_data)
    # # 判断是否为IP数据报
    if not isinstance(eth.data, dpkt.ip.IP):
        print("Non IP packet type not supported ", eth.data.__class__.__name__)
        return
    # 抓IP数据包
    packet = eth.data
    # 取出分片信息
    df = bool(packet.off & dpkt.ip.IP_DF)
    mf = bool(packet.off & dpkt.ip.IP_MF)
    offset = packet.off & dpkt.ip.IP_OFFMASK

    # 输出数据包信息：time,src,dst,protocol,length,ttl,df,mf,offset,checksum
    output1 = {'time': time.strftime('%Y-%m-%d %H:%M:%S', (time.localtime()))}
    output2 = {'src': '%d.%d.%d.%d' % tuple(packet.src), 'dst': '%d.%d.%d.%d' % tuple(packet.dst)}
    output3 = {'protocol': packet.p, 'len': packet.len, 'ttl': packet.ttl}
    output4 = {'df': df, 'mf': mf, 'offset': offset, 'checksum': packet.sum}
    print()
    print(output1)
    print(output2)
    print(output3)
    print(output4)


# WinPcapUtils这两个类用来捕获和发送流量，本文主要讲述数据包的捕获。
WinPcapUtils.capture_on(pattern="Realtek PCIe GBE Family Controller", callback=packet_callback)

'''
winpcapy提供了两种通过制定网络设备的抓包方式，一种是通过设备的描述去模糊匹配 符合该描述的第一个设备，另一种是直接拿设备的设备名去匹配。
分别对应WinPcapUtils.capture_on(pattern, callback)和WinPcapUtils.capture_on_device_name(device_name, callback)，
无论是那种方式，归根结底都是要拿设备名称去抓捕对应的流量，但是通过设备名更加的精确(capture_on_device_name)，
如果不知道自己是需要 抓本机那个设备的流量，可以本地通过命令行ipconfig /all查看自己设备的描述，
拿着该设备的描述通过WinPcapDevices.list_devices()函数返回的{‘设备名称’:‘设备描述’}字典 来对应设备名。


capture_on_device_name提供两个参数，一个是设备名称，另一个是回调函数
回调函数接收四个参数，直接套用了pcap中packet_handler函数，只不过包装了成了python可以使用的
win_pcap是嗅探对象本身，win_pcap.stop()可以停止嗅探
param可以先不用管
header.contents中有caplen,len,ts属性，caplen是可以参看捕获的数据帧的长度，len一般情况下等于caplen，ts中含有tv_sec和tv_usec属性，分别是数据包发送时的时间戳以及微秒数，pkt_data是数据包本身。

dpkt提供了解析数据帧的功能，也提供了将数据帧储存为pcap文件的能力
dpkt.pcap.Writer(f_pcap).writepkt(pdata, ptime)

'''
